// 按考试成绩汇总

package student

import (
	"api/common"
	"api/common/logger"
	"api/common/orm"
	"api/common/web"
	"fmt"
	"net/http"
	"strings"
)

// @TagName 按考试成绩汇总
// @Controller SumController
type SumController struct{}

// @Title 学生列表数据
// @Route /sum/list --> List
// @Param {"deptId":0, "sum":0}
// @Method post
func (this *SumController) List(w http.ResponseWriter, r *http.Request) {
	defer web.PanicHandler(w, r)
	inputJson, msg := web.TokenCheckRequest(r)
	if msg != nil {
		web.ServeJSON(w, msg)
		return
	}

	// 获取系部和专业的对应关系
	sql := "select a.id," +
		"(select group_concat(b.id) from basic_special b where b.pid = a.id) ids" +
		" from basic_special a where a.pid = 0"
	conn := orm.NewOrm()
	deptData, err := conn.Raw(sql).QueryMaps()
	if err != nil {
		logger.Error("获取系部和专业的对应关系发生错误", err)
		web.ServeJSON(w, web.JsonMsg{false, "获取系部和专业的对应关系发生错误" + err.Error(), 1})
		return
	}

	mappingDept := map[string]string{}
	for _, item := range deptData {
		id := common.ToStr(item["id"])
		ids := common.ToStr(item["ids"])
		mappingDept[id] = ids
	}

	// 获取专业列表数据
	sql = "select id, `name` from basic_special where pid > 0"
	specialData, err := conn.Raw(sql).QueryMaps()
	if err != nil {
		logger.Error("获取专业列表数据发生错误", err)
		web.ServeJSON(w, web.JsonMsg{false, "获取专业列表数据发生错误" + err.Error(), 1})
		return
	}

	mappingSpecial := map[string]string{}
	for _, item := range specialData {
		id := common.ToStr(item["id"])
		name := common.ToStr(item["name"])
		mappingSpecial[id] = name
	}

	wheres, limit := web.SerachJsonToSql(inputJson)
	where := " where `status` = 5 and `exit` = false" // 5: 交费成功，且未退学
	if len(wheres) > 0 {
		where += " and "
		where += strings.Join(wheres, " and ")
	}

	deptId := inputJson["deptId"]
	if deptId != nil {
		value := mappingDept[common.ToStr(deptId)]
		if value != "" {
			where += " and special_id in (" + value + ")"
		}
	}

	sum := inputJson["sum"]
	sumMin := 0
	sumMax := 1000
	if sum != nil {
		sumMin = int(sum.(float64))
		sumMax = sumMin + 100
	}
	where += " and `sum` >= %d and `sum` < %d"
	where = fmt.Sprintf(where, sumMin, sumMax)

	type Counts struct {
		Total        uint32 `json:"total"`
		Lodging1sex1 uint32 `json:"lodging1sex1"`
		Lodging1sex0 uint32 `json:"lodging1sex0"`
		Lodging0sex1 uint32 `json:"lodging0sex1"`
		Lodging0sex0 uint32 `json:"lodging0sex0"`
	}
	counts := &Counts{}
	sql = "select" +
		" (select count(1) from student_info" + where + ") total," +
		" (select count(1) from student_info" + where + " and lodging=true  and sex=true)  lodging1sex1," +
		" (select count(1) from student_info" + where + " and lodging=true  and sex=false) lodging1sex0," +
		" (select count(1) from student_info" + where + " and lodging=false and sex=true)  lodging0sex1," +
		" (select count(1) from student_info" + where + " and lodging=false and sex=false) lodging0sex0"
	err = conn.Raw(sql).QueryRow(counts)
	if err != nil {
		logger.Error("查询记录数量发生错误", err)
		web.ServeJSON(w, web.JsonMsg{false, "查询记录数量发生错误" + err.Error(), 1})
		return
	}

	data := []map[string]interface{}{}
	if counts.Total > 0 {
		sql = "select * from student_info" + where + " order by `sum` desc" + limit
		data, err = conn.Raw(sql).QueryMaps()
		if err != nil {
			logger.Error("查询记录发生错误", err)
			web.ServeJSON(w, web.JsonMsg{false, "查询记录发生错误" + err.Error(), 1})
			return
		}
	}

	for _, item := range data {
		specialId := common.ToStr(item["specialId"])
		specialName := mappingSpecial[specialId]
		typeValue := common.ToStr(item["type"])
		typeName := mappingType[typeValue]
		item["specialName"] = specialName + " - " + typeName
	}

	result := map[string]interface{}{}
	result["status"] = 0
	result["success"] = true
	result["msg"] = "查询成功"
	result["data"] = data
	result["counts"] = counts
	web.ServeJSON(w, result)
}

// @Title 带统计人数的系部树形数据
// @Route /sum/tree --> Tree
// @Method post
func (this *SumController) Tree(w http.ResponseWriter, r *http.Request) {
	defer web.PanicHandler(w, r)
	_, msg := web.TokenCheckRequest(r)
	if msg != nil {
		web.ServeJSON(w, msg)
		return
	}

	// 获取系部数据
	sql := "select a.id `key`, a.`name` title, (" +
		"select count(1) from student_info i where i.`status` = 5 and `exit` = false and i.special_id in (" +
		"select b.id from basic_special b where b.pid = a.id" +
		")) `count` from basic_special a where a.pid = 0 order by `count` desc"
	conn := orm.NewOrm()
	deptData, err := conn.Raw(sql).QueryMaps()
	if err != nil {
		logger.Error("获取系部数据发生错误", err)
		web.ServeJSON(w, web.JsonMsg{false, "获取系部数据发生错误" + err.Error(), 1})
		return
	}

	// 获取最高分
	sumUpper := 0
	sql = "select `sum` from student_info" +
		" where `status` = 5 and `exit` = false" +
		" order by `sum` desc limit 1"
	err = conn.Raw(sql).QueryRow(&sumUpper)
	if err != nil {
		if !strings.Contains(err.Error(), "no row found") {
			logger.Error("获取最高分发生错误", err)
			web.ServeJSON(w, web.JsonMsg{false, "获取最高分发生错误" + err.Error(), 1})
			return
		}
	}

	if sumUpper > 0 {
		sumUpper = (sumUpper/100 + 1) * 100
	}

	// 统计每个系部下的学生考试成绩
	step := 100
	for _, deptItem := range deptData {
		// 获取学生数量
		deptId := common.ToStr(deptItem["key"])

		for sum := sumUpper; sum > 0; sum -= step {
			sumCurrent := sum - step
			count := 0
			sql = "select count(1) from student_info i" +
				" where i.`status` = 5 and `exit` = false" +
				" and `sum` >= %d and `sum` < %d" +
				" and i.special_id in (" +
				"select b.id from basic_special b where b.pid = ?" +
				") order by `sum` desc"
			sql = fmt.Sprintf(sql, sumCurrent, sum)
			err = conn.Raw(sql, deptId).QueryRow(&count)
			if err != nil {
				logger.Error("获取学生数量发生错误", err)
				web.ServeJSON(w, web.JsonMsg{false, "获取学生数量发生错误" + err.Error(), 1})
				return
			}

			if count >= 1 {
				if deptItem["children"] == nil {
					deptItem["children"] = []map[string]interface{}{}
				}
				childData := deptItem["children"].([]map[string]interface{}) // 断言
				sumItem := map[string]interface{}{}
				sumItem["key"] = deptId + "_" + common.ToStr(sumCurrent)
				sumItem["title"] = fmt.Sprintf("%d ～ %d分：%d人", sumCurrent, sum, count)
				sumItem["deptName"] = deptItem["title"]
				childData = append(childData, sumItem)
				deptItem["children"] = childData
			}
		}

		deptTitle := common.ToStr(deptItem["title"])
		deptTitle += "：" + common.ToStr(deptItem["count"]) + "人"
		deptItem["title"] = deptTitle
		deptItem["selectable"] = false // 系部不可选
		delete(deptItem, "count")
	}

	web.ServeJSON(w, web.List{0, true, "查询成功", deptData})
}

// 报考类别: 1:职教高考, 2:职业中专, 3:职业中专(3+2), 4:技工, 5:技工(3+2)
var mappingType = map[string]string{
	"1": "职教高考",
	"2": "职业中专",
	"3": "职业中专(3+2)",
	"4": "技工",
	"5": "技工(3+2)",
}
